/**
 * 
 */
package common.project.epic.ui;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.HTTP;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Looper;
import android.os.Parcelable;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.MimeTypeMap;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import common.project.epic.core.LocationEpicService;
import common.project.epic.db.CurrentUser;

/**
 * @author Luca & Andrea
 *
 */
public class Login extends Activity implements OnClickListener {
	public static final String TAG = "Epic: Login Activity";
    public static final boolean DEBUG = EpicDebugUI.DEBUG;
    
    public static final String PREF_FILE = "ApplicationPreferencesFile";
	private static final String PREF_REMEMBER_ME = "remember_me";
	private static final String PREF_REMEMBERED_USERNAME = "remembered_username";
	private static final String PREF_REMEMBERED_PASSWORD = "remembered_password";
	private static final String NUMBER_OF_ACCOUNTS = "number_of_accounts";
	protected static final String UPDATE_URL = "http://www.epic.vidaleluca.com/login.php";
	
	private ImageView facebook_link;
	private ImageView twitter_link;
	private EditText username;
	private EditText password;
	private String str_username;
	private String str_password;
	private Button login_button;
	private TextView create_account_text;
	private CheckBox remember_me;
	private ProgressDialog progressDialog;
	private SharedPreferences pref;
	private int noa; 
	private boolean is_account_in_pref;
	private  Intent addAttachIntent;
	private boolean isCalledFromContentSharing;
	private static String C2DM_ACCOUNT = "epic.c2dm@gmail.com";
	private static Typeface tfNormal;
	private static Typeface tfBold;
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	    setContentView(R.layout.login);
	    
	    tfNormal = Typeface.createFromAsset(getBaseContext().getAssets(), "font/Arial.ttf");
	    tfBold = Typeface.createFromAsset(getBaseContext().getAssets(), "font/ArialBold.ttf");
	    
	    isCalledFromContentSharing = false;
	    Intent tmp_callingIntent = getIntent();
	    Bundle extras = tmp_callingIntent.getExtras();
	    String action = tmp_callingIntent.getAction();
	    if(action == null){
	    	// not share content
	    }
	    else{
		    
	    	if(action.equals(!action.equals(Intent.ACTION_MAIN))){
		    	// not share content
		    }
	    	else{
		        if(action.equals(Intent.ACTION_SEND)){
			        if(extras.containsKey(Intent.EXTRA_STREAM)){
	//		        	String mime_type = tmp_callingIntent.resolveType(getContentResolver());
			        	final Uri uri = (Uri) extras.getParcelable(Intent.EXTRA_STREAM);
			        	ContentResolver cr = getContentResolver();
		        		String mime_type = cr.getType(uri);
			        	addAttachIntent = new Intent(Login.this, EpicNewMsg.class);
			        	addAttachIntent.putExtra("content", uri);
			        	if(mime_type.substring(0, 3).equals("ima")) {
			    	    	addAttachIntent.putExtra("mime_type", EpicNewMsg.ATTACH_IMAGE);
			    	    }
			        	else if(mime_type.substring(0, 3).equals("aud")) {
			    	    	addAttachIntent.putExtra("mime_type", EpicNewMsg.ATTACH_AUDIO);
			    	    }
			        	else if(mime_type.substring(0, 3).equals("vid")) {
			    	    	addAttachIntent.putExtra("mime_type", EpicNewMsg.ATTACH_VIDEO);
			    	    }
			        	else {
			        		addAttachIntent.putExtra("mime_type", EpicNewMsg.ATTACH_FILE);
			        	}
			        	addAttachIntent.setAction("SHARE_TO_EPIC");
			        	isCalledFromContentSharing = true;
			        }
		        }
		        if(action.equals(Intent.ACTION_SEND_MULTIPLE)){
		        	if(extras.containsKey(Intent.EXTRA_STREAM)){
	//	        		String mime_type_array = tmp_callingIntent.resolveType(getContentResolver());
			        	final ArrayList<Parcelable> array_list = extras.getParcelableArrayList(Intent.EXTRA_STREAM);
			        	ArrayList<Integer> mime_type_list = new ArrayList<Integer>();
			        	String ext = "";
			        	for(Parcelable item:array_list) {
			        		Uri uri_tmp = (Uri)item;
			        		ContentResolver cr = getContentResolver();
			        		String uri_type = cr.getType(uri_tmp);
			        		if(uri_type == null){
			        			String path="";
			        			File tmp_file = new File(uri_tmp.getPath());
			        	        if(tmp_file.exists()){
			        	                path = uri_tmp.getPath();
			        	                try {
			        	                	ext = MimeTypeMap.getFileExtensionFromUrl(tmp_file.toURL().toString());
			        	                	ext = resolveToCategory(ext).substring(0, 3);
										} catch (MalformedURLException e) {
											e.printStackTrace();
										}
			        	        };
			        		}
			        		else{
			        			ext = cr.getType(uri_tmp).substring(0, 3);
			        		}
			        		
			        		if(ext.equals("ima")) {
			        			mime_type_list.add(EpicNewMsg.ATTACH_IMAGE);
			        		}
			        		else if(ext.equals("aud")) {
			        			mime_type_list.add(EpicNewMsg.ATTACH_AUDIO);
			        		}
			        		else if(ext.equals("vid")) {
			        			mime_type_list.add(EpicNewMsg.ATTACH_VIDEO);
			        		}
			        		else {
			        			mime_type_list.add(EpicNewMsg.ATTACH_FILE);
				        	}
			        	}
			        	addAttachIntent = new Intent(Login.this, EpicNewMsg.class);
			        	addAttachIntent.putExtra("content", array_list);
			        	addAttachIntent.putIntegerArrayListExtra("mime_type_list", mime_type_list);
			        	addAttachIntent.setAction("MULTIPLE_SHARE_TO_EPIC");
			        	isCalledFromContentSharing = true;
		        	}
		        }
	        }
	    }
        if(extras != null){
	        if(extras.containsKey("username") && extras.containsKey("password")) {
	        	str_username = extras.getString("username");
	        	str_password = extras.getString("password");
	        }
        }
	    initializeUI(str_username,str_password);
	}

	private String resolveToCategory(String type) {
		String extra_type="";
		if(type.equals("png") || type.equals("jpg")|| type.equals("bmp")|| type.equals("gif")){
				extra_type = "image/"+ type;
			}
		else
		if( type.equals("aac")|| type.equals("m4a")|| type.equals("wav")|| type.equals("mid") || type.equals("mp3")){
        		extra_type = "audio/"+ type;
        	}
		else 
		if(type.equals("3gp") || type.equals("mp4")||type.equals("m4v")){
        		extra_type = "video/"+ type;
        	}
		return extra_type;
	}

	private void initializeUI(String usr, String psw) {
		if(DEBUG) {
    		Log.d(TAG, "initializeUI()");
    	}
		
		pref = getSharedPreferences(PREF_FILE, MODE_PRIVATE);
		
		login_button = (Button)findViewById(R.id.login_button);	
		create_account_text = (TextView)findViewById(R.id.create_account_text);
		username = (EditText)findViewById(R.id.username_ET);
	    password = (EditText)findViewById(R.id.password_ET);
	    remember_me = (CheckBox)findViewById(R.id.remember_me_CB);
	    username.setTypeface(tfNormal);
	    password.setTypeface(tfNormal);
	    remember_me.setTypeface(tfBold);
//	    facebook_link = (ImageView)findViewById(R.id.social_facebook_logo);
//	    twitter_link = (ImageView)findViewById(R.id.social_twitter_logo);
	    
	    if(pref.getBoolean(PREF_REMEMBER_ME, false)) {
	    	// if remember_me CheckBox was previously checked: 
	    	//   retrieve the remembered values in pref file 
	    	//   fill username and password EditText  
	    	username.setText(pref.getString(PREF_REMEMBERED_USERNAME, null));
			password.setText(pref.getString(PREF_REMEMBERED_PASSWORD, null));
			remember_me.setChecked(true);
	    }
	    else {
	    	// if remember_me CheckBox was NOT checked: 
	    	//   if the calling activity is CreateAccount <=> usr and psw are not null: 
	    	//     fill username and password EditText
	    	//   else
	    	//     do nothing (user has to fill username and password EditText)
	    	if(!(usr == null && psw == null)){
				username.setText(usr);
				password.setText(psw);
			}
	    	else {
//	    		username.setText("");
//	    		password.setText("");
	    	}
	    }
	    
		login_button.setOnClickListener(this);
		create_account_text.setOnClickListener(this);
//		facebook_link.setOnClickListener(this);
//		twitter_link.setOnClickListener(this);
		
		
		//Set up of progress dialog
		progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Please wait...");
        progressDialog.setIndeterminate(true);
        progressDialog.setCancelable(false);
	}
	
	private int accountIndex;
	public void onClick(View v) {
		
		if(v.getId() == R.id.create_account_text) {
			if(isOnline()) {
				Intent intentCreateAccount = new Intent(Login.this, CreateAccount.class);
				startActivity(intentCreateAccount);
			}
			else {
				Toast.makeText(getApplicationContext(), "Enable data connection \n" +
						"to CREATE A NEW ACCOUNT", 2000).show();
			}
		}
		
//		if(v.getId() == R.id.social_twitter_logo) {
//			String url = "https://twitter.com/#!/Epic_App";
//			Intent i = new Intent(Intent.ACTION_VIEW);
//			i.setData(Uri.parse(url));
//			startActivity(i);
//		}
//		
//		if(v.getId() == R.id.social_facebook_logo) {
//			String url = "http://www.facebook.com/epicapp";
//			Intent i = new Intent(Intent.ACTION_VIEW);
//			i.setData(Uri.parse(url));
//			startActivity(i);
//		}
//		
		if(v.getId() == R.id.login_button) {	
			is_account_in_pref = false;
			noa = pref.getInt(NUMBER_OF_ACCOUNTS,0);
			
			if(noa>0) {
				for(int i=1; i<=noa; i++) {
					if((username.getText().toString()).equals(pref.getString("username_"+i,null)) 
							&& 
							( (md5(password.getText().toString())).equals(pref.getString("password_"+i,null)) ||
								(password.getText().toString()).equals(pref.getString("password_"+i,null)) )) {
						is_account_in_pref = true;
						accountIndex = i;
						break;
					}
				}
			}
			
			if(!is_account_in_pref) {
				 if(isOnline()) {
				     //TODO create http connection and perform the check in SERVER DB
					 if(username.getText().toString().length()>0 && password.getText().toString().length()>0){						 
						 progressDialog.show();	 
						 doLogin(username.getText().toString(),password.getText().toString());
					 }
					 else {
						 Toast.makeText(getApplicationContext(), "Fill username and password", 2000).show();
					 }
				 } 
				 else {
					 if(username.getText().toString().length()>0 && password.getText().toString().length()>0) {
						//ask user to enable data connection
						 Toast.makeText(getApplicationContext(), 
								 "Account locally not found \n" +
								 "Enable data connection for SERVER VALIDATION", 2000).show();
					 }
					 else {
						 Toast.makeText(getApplicationContext(), "Fill username and password", 2000).show();
					 }
				 }
			}
			else {
				CurrentUser.readCurrentUserSettings(getApplicationContext());
				str_username = username.getText().toString();
				str_password = pref.getString("password_"+accountIndex,null); // must be the md5(psw) 
				// TODO logged_username = md5(str_username(==mail), EpicKey) 
				pref.edit().putString("logged_username", str_username).commit();
				pref.edit().putString("logged_password", str_password).commit();
				// 1) set current account (username & md5(password))
	    		CurrentUser.setCurrentUsername(str_username);
	        	CurrentUser.setCurrentPassword(str_password);
				if(remember_me.isChecked()) {
					pref.edit()
					.putString(PREF_REMEMBERED_USERNAME, str_username)
					.putString(PREF_REMEMBERED_PASSWORD, str_password)
					.putBoolean(PREF_REMEMBER_ME, true)
					.commit();
				}
				else {
					pref.edit()
					.putString(PREF_REMEMBERED_USERNAME, null)
					.putString(PREF_REMEMBERED_PASSWORD, null)
					.putBoolean(PREF_REMEMBER_ME, false)
					.commit();
				}
				// TODO ???
	        	Intent intentLocationService = new Intent(Login.this, LocationEpicService.class);
				startService(intentLocationService);
				
				if(!isCalledFromContentSharing){
					Intent intentEpic = new Intent(Login.this, Epic.class);
					startActivity(intentEpic);
				}
				else {
					isCalledFromContentSharing = false;
					startActivity(addAttachIntent);
				}
			}
		}
	}
	
	private void performC2DMRegistration() {
		// TODO Auto-generated method stub
		Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
		registrationIntent.putExtra("app", PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(), 0));
		registrationIntent.putExtra("sender", C2DM_ACCOUNT);
		getApplicationContext().startService(registrationIntent);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
	    MenuInflater inflater = getMenuInflater();
	    inflater.inflate(R.menu.login_menu, menu);
	    return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
	    // Handle item selection
	    switch (item.getItemId()) {
	    case R.id.login_close_option:
	        finish();
	        return true;
	    case R.id.login_help_option:
	        showHelp();
	        return true;
	    default:
	        return super.onOptionsItemSelected(item);
	    }
	}
	
	private void showHelp() {
		Toast.makeText(Login.this, "Epic-project web", Toast.LENGTH_LONG).show();
	}
	
	public boolean isOnline() {
		ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo ni = cm.getActiveNetworkInfo();
		if(ni != null){
			return cm.getActiveNetworkInfo().isConnectedOrConnecting();
		}
		else {
			return false;
		}
	}

	private void doLogin(final String username, final String pass) {
		 
        final String password_md5 = md5(pass);
        
        Thread t = new Thread() {
 
            public void run() {
                Looper.prepare();
                DefaultHttpClient client = new DefaultHttpClient();
                HttpConnectionParams.setConnectionTimeout(client.getParams(), 15000);                
                HttpResponse response;
                HttpEntity entity;        
                try {
 
                    HttpPost post = new HttpPost(UPDATE_URL);
                    List <NameValuePair> nvps = new ArrayList <NameValuePair>();
                    nvps.add(new BasicNameValuePair("username", username));
                    nvps.add(new BasicNameValuePair("password", password_md5));
                    post.setHeader("Content-Type", "application/x-www-form-urlencoded");
                    post.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
                    response = client.execute(post);
                    entity = response.getEntity();
                    InputStream is = entity.getContent();
                    read(is);
                    is.close();
//                    C2DMessaging.register(Login.this, C2DM_ACCOUNT);
                    if (entity != null) entity.consumeContent();
                } catch (Exception e) {
                    progressDialog.dismiss();
                    createDialog("Error", "Couldn't establish a connection");
                }
                Looper.loop();                
            }
        };
 
        t.start();
 
    }
	
	//create a alert dialog
	//@params String
	//@params String
	
    private void createDialog(String title, String text) {
    	 
        AlertDialog ad = new AlertDialog.Builder(this)
 
        .setPositiveButton("Ok", null)
 
        .setTitle(title)
 
        .setMessage(text)
 
        .create();
 
        ad.show();
 
    }
    
	// Read an input stream and pass it to LoginContentHandler
    //@params InputStream
    
    private void read(InputStream in) {
    	 
        SAXParserFactory spf = SAXParserFactory.newInstance();
 
        SAXParser sp;
 
        try {
 
            sp = spf.newSAXParser();
 
            XMLReader xr = sp.getXMLReader();
 
            LoginContentHandler uch = new LoginContentHandler();
 
            xr.setContentHandler(uch);
 
            xr.parse(new InputSource(in));
 
        } catch (ParserConfigurationException e) {
 
        } catch (SAXException e) {
 
        } catch (IOException e) {}
 
    }  
	

    private class LoginContentHandler extends DefaultHandler {
 
        private boolean in_loginTag = false;
 
        private String userID;
 
        boolean error_occured = false;
 
 
 
        public void startElement(String n, String l, String q, Attributes a)
 
            throws SAXException {
 
            if(l == "login") {
            	in_loginTag = true; 
            }
 
            if(l == "error") {
 
                progressDialog.dismiss();
                
                if(Integer.parseInt(a.getValue("value")) == 1)
 
                    createDialog("Error", "Couldn't connect to Database");
 
                if(Integer.parseInt(a.getValue("value")) == 2)
 
                    createDialog("Error", "Error in Database: Table missing");
 
                if(Integer.parseInt(a.getValue("value")) == 3)
 
                    createDialog("Error", "Retype username or password");
                
                if(Integer.parseInt(a.getValue("value")) == 4)
                	 
                    createDialog("Error", "Please change your username");
 
                error_occured = true;
 
            }
 
            if(l == "user" && in_loginTag && a.getValue("id") != "")            
            	
                userID = a.getValue("id");
            	
        }
 
         
 
        public void endElement(String n, String l, String q) throws SAXException {
 
            if(l == "login") {
 
                in_loginTag = false;
 
                if(!error_occured) {
 
                    progressDialog.dismiss();
                    //register to C2DM
                    performC2DMRegistration();
                    Intent i = new Intent(getApplicationContext(),Epic.class);
                    i.putExtra("user_id", userID);
                    quit(error_occured,i);
                }
            }
        }

        public void characters(char ch[], int start, int length) { }
 
        public void startDocument() throws SAXException { }
 
        public void endDocument() throws SAXException { }
 
    }

    	
    private void quit(boolean error_occured, Intent i) {
    	if(!error_occured) {
    		str_username = username.getText().toString();
    		str_password = password.getText().toString();
        	
        	noa = pref.getInt(NUMBER_OF_ACCOUNTS, 0);
        	noa++;
        	pref.edit()
			.putInt(NUMBER_OF_ACCOUNTS, noa)
        	.putString("username_"+noa, str_username)
        	.putString("password_"+noa, md5(str_password))
        	.putString("logged_username", str_username)
        	.putString("logged_password", md5(str_password))
        	.commit();
    		
			if(remember_me.isChecked()) {
				pref.edit()
				.putString(PREF_REMEMBERED_USERNAME, str_username)
				.putString(PREF_REMEMBERED_PASSWORD, md5(str_password))
				.putBoolean(PREF_REMEMBER_ME, true)
				.commit();
			}
			else {
				pref.edit()
				.putString(PREF_REMEMBERED_USERNAME, null)
				.putString(PREF_REMEMBERED_PASSWORD, null)
				.putBoolean(PREF_REMEMBER_ME, false)
				.commit();
			}
			// 1) set current account (username & md5(password))
    		CurrentUser.setCurrentUsername(str_username);
        	CurrentUser.setCurrentPassword(md5(str_password));
        	// 2) write the "username" file with the CurrentUser fields values
        	//    in this case we set only username and md5(password) and the other values are the default ones
        	CurrentUser.writeCurrentUserSettings(getApplicationContext());
        	// 3) CurrentUser.username has to be set (done in 1))
        	//    we retrive the other values and fill the CurrentUser fields with the settings saved in "username" file 
        	CurrentUser.readCurrentUserSettings(getApplicationContext());
        	Intent intentloc = new Intent(this, LocationEpicService.class);
	    	startService(intentloc);
			startActivity(i);
		}
		else {
			Toast.makeText(getApplicationContext(), "Account not valid! \n" +
					"Try to retype or create a new account", 2000).show();
		}
    }
	
	//generate md5 digest
	//@params String

	private String md5(String in) {
		 
        MessageDigest digest;
 
        try {
 
            digest = MessageDigest.getInstance("MD5");
 
            digest.reset();        
 
            digest.update(in.getBytes());
 
            byte[] a = digest.digest();
 
            int len = a.length;
 
            StringBuilder sb = new StringBuilder(len << 1);
 
            for (int i = 0; i < len; i++) {
 
                sb.append(Character.forDigit((a[i] & 0xf0) >> 4, 16));
 
                sb.append(Character.forDigit(a[i] & 0x0f, 16));
 
            }
 
            return sb.toString();
 
        } catch (NoSuchAlgorithmException e) { e.printStackTrace(); }
 
        return null;
 
    }

}
